﻿using System.Reflection;
using Autofac;
using BlogSystem.Common.Config.DI.annotation;

namespace BlogSystem.Common.Config.DI;

public static class IocManager
{
    /// <summary>
    /// 批量注入 扩展
    /// </summary>
    /// <param name="builder"></param>
    /// <param name="assembly"></param>
      public static void BatchAutowired(this ContainerBuilder builder, Assembly assembly)
    {
        foreach (Type type in assembly.GetTypes())   
        {
            Console.WriteLine(type.FullName); // 输出类型的全名
        }
 
        var transientType = typeof(ITransientDenpendency); //瞬时注入
        var singletonType = typeof(ISingletonDenpendency); //单例注入 
        var scopedType = typeof(IScopedDenpendency); //生命周期注入
        
        //  //瞬时注入
        // builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(transientType))
        //     .AsSelf()
        //     .AsImplementedInterfaces()
        //     .InstancePerDependency()
        //     .PropertiesAutowired(new AutowiredPropertySelector());
        // //单例注入
        // builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(singletonType))
        //     .AsSelf()
        //     .AsImplementedInterfaces()
        //     .SingleInstance()
        //     .PropertiesAutowired(new AutowiredPropertySelector());
        // //生命周期注入
        // builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(scopedType))
        //     .AsSelf()
        //     .AsImplementedInterfaces()
        //     .InstancePerLifetimeScope()
        //     .PropertiesAutowired(new AutowiredPropertySelector());
        
        
        //瞬时注入
        builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract 
                                                                     && _judgeAttribute(t,"transient"))
            .AsSelf()
            //.AsImplementedInterfaces()
            .As(t =>
            {
                var interfaces = t.GetInterfaces();
                if (interfaces.Any())
                {
                    return new[] { t }.Concat(interfaces);
                }else {
                    return new[] { t };
                }
            })
            .InstancePerDependency()
            .PropertiesAutowired(new AutowiredPropertySelector());
        //单例注入
        builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract
                                                                     && _judgeAttribute(t,"single"))
            .AsSelf()
            // .AsImplementedInterfaces()
            .As(t =>
            {
                var interfaces = t.GetInterfaces();
                if (interfaces.Any())
                {
                    return new[] { t }.Concat(interfaces);
                }else
                {
                    return new[] { t };
                }
            })
            .SingleInstance()
            .PropertiesAutowired(new AutowiredPropertySelector());
        //生命周期注入
        builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract &&  
                                                           _judgeAttribute(t,"scoped"))
            .AsSelf()
           // .AsImplementedInterfaces()
            .As(t =>
            {
                var interfaces = t.GetInterfaces();
                if (interfaces.Any())
                {
                    return new[] { t }.Concat(interfaces);
                }else
                {
                    return new[] { t };
                }
            })
            .InstancePerLifetimeScope()
            .PropertiesAutowired(new AutowiredPropertySelector());
    }
      
      private static bool _judgeAttribute(Type type,string iocType)
      {
          var attribute = type.GetCustomAttribute<IocAttribute>();
          if (attribute != null)
          {
              if (iocType.Equals(attribute.Value))
              {
                  return true;
              }
          }
          return false;
      }

}